package com.ma.implatform.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ma.implatform.constant.RedisKey;
import com.ma.implatform.entity.GroupMember;
import com.ma.implatform.mapper.GroupMemberMapper;
import com.ma.implatform.service.GroupMemberService;
import com.ma.implatform.utils.DateTimeUtils;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@CacheConfig(cacheNames = RedisKey.IM_CACHE_GROUP_MEMBER_ID)
public class GroupMemberServiceImpl extends ServiceImpl<GroupMemberMapper, GroupMember> implements GroupMemberService {
    @CacheEvict(key = "#groupMember.getGroupId()")
    @Override
    public boolean save(GroupMember groupMember){
        return super.save(groupMember);
    }
    @CacheEvict(key = "#groupId")
    @Override
    public GroupMember findByGroupAndUserId(Long groupId, Long userId) {
        LambdaQueryWrapper<GroupMember> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(GroupMember::getGroupId,groupId);
        wrapper.eq(GroupMember::getUserId,userId);
        return this.getOne(wrapper);
    }

    @Override
    public List<GroupMember> findByUserId(Long userId) {
        LambdaQueryWrapper<GroupMember> memberWrapper = Wrappers.lambdaQuery();
        memberWrapper.eq(GroupMember::getUserId,userId).eq(GroupMember::getQuit,false);
        return this.list(memberWrapper);
    }

    @Override
    public List<GroupMember> findQuitInMonth(Long userId) {
        Date monthTime = DateTimeUtils.addMonths(new Date(), -1);
        LambdaQueryWrapper<GroupMember> memberWrapper = Wrappers.lambdaQuery();
        memberWrapper.eq(GroupMember::getUserId,userId)
                .eq(GroupMember::getQuit,true)
                .ge(GroupMember::getQuitTime,monthTime);
        return this.list(memberWrapper);
    }

    @Override
    public List<GroupMember> findByGroupId(Long groupId) {
        LambdaQueryWrapper<GroupMember> memberWrapper = Wrappers.lambdaQuery();
        memberWrapper.eq(GroupMember::getGroupId,groupId);
        return this.list(memberWrapper);
    }

    @Override
    public List<Long> findUserIdsByGroupId(Long groupId) {
        LambdaQueryWrapper<GroupMember> memberWrapper = Wrappers.lambdaQuery();
        memberWrapper.eq(GroupMember::getGroupId,groupId).eq(GroupMember::getQuit, false).select(GroupMember::getUserId);
        List<GroupMember> members = this.list(memberWrapper);
        return members.stream().map(GroupMember::getUserId).collect(Collectors.toList());
    }

    @Override
    public boolean saveOrUpdateBatch(Long groupId, List<GroupMember> members) {
        return super.saveOrUpdateBatch(members);
    }

    @Override
    public void removeByGroupId(Long groupId) {
        LambdaUpdateWrapper<GroupMember> wrapper = Wrappers.lambdaUpdate();
        wrapper.eq(GroupMember::getGroupId,groupId).set(GroupMember::getQuit,true)
                .set(GroupMember::getQuitTime,new Date());
        this.update(wrapper);

    }

    @Override
    public void removeByGroupAndUserId(Long groupId, Long userId) {
        LambdaUpdateWrapper<GroupMember> wrapper = Wrappers.lambdaUpdate();
        wrapper.eq(GroupMember::getGroupId,groupId).eq(GroupMember::getUserId,userId)
                .set(GroupMember::getQuit,true)
                .set(GroupMember::getQuitTime,new Date());
        this.update(wrapper);
    }
    @CacheEvict(key = "#groupId")
    @Override
    public void removeByGroupAndUserIds(Long groupId, List<Long> userIds) {
        LambdaUpdateWrapper<GroupMember> wrapper = Wrappers.lambdaUpdate();
        wrapper.eq(GroupMember::getGroupId,groupId);
        wrapper.in(GroupMember::getUserId,userIds);
        wrapper.set(GroupMember::getQuit,true);
        wrapper.set(GroupMember::getQuitTime,new Date());
        this.update(wrapper);
    }

    @Override
    public Boolean isInGroup(Long groupId, List<Long> userIds) {
        if (CollectionUtils.isEmpty(userIds)){
            return true;
        }
        LambdaQueryWrapper<GroupMember> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(GroupMember::getGroupId,groupId);
        wrapper.eq(GroupMember::getQuit,false);
        wrapper.in(GroupMember::getUserId,userIds);

        return userIds.size() == this.count(wrapper);
    }

    @Override
    public void setDnd(Long groupId, Long userId, Boolean isDnd) {
        LambdaUpdateWrapper<GroupMember> wrapper = Wrappers.lambdaUpdate();
        wrapper.eq(GroupMember::getGroupId,groupId);
        wrapper.eq(GroupMember::getUserId,userId);
        wrapper.set(GroupMember::getIsDnd,isDnd);
        this.update(wrapper);
    }
}
